﻿using System;
using System.Collections.Generic;
using System.Linq;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.Logic;
using UnityEditor;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay.Editors
{
    public class BattleEditorWindow : EditorWindow
    {
        private static BattleEditorWindow _instance;

        public static BattleEditorWindow Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = CreateWindow<BattleEditorWindow>("BattleEditor");
                }

                return _instance;
            }
        }

        [MenuItem("GameEditor/BattleDebug/BattleEditorWindow", false, 100)]
        public static void Open()
        {
            Instance.Show();
        }


        private List<Unit> _selectUnits = new List<Unit>();

        private Vector2 _Scroll;
        private Vector2 _UnitsScroll;

        private bool _showLocalProperty = false;
        private bool _ShowProperty = true;
        private bool _ShowPropertyDetail = false;
        private bool _ShowSkill;
        private bool _ShowBuff;
        private bool _ShowCustomProperty;

        private int _TempSkill;
        private int _TempSkillLv;
        private Dictionary<long, int> _TempBuffID = new Dictionary<long, int>();

        private void OnInspectorUpdate()
        {
            Repaint();
        }

        private void OnGUI()
        {
            if (!Application.isPlaying)
            {
                GUILayout.Label("进入战斗后使用");
                return;
            }

            Battle battle = null;
            if (SBattleLogicModule.Instance.battleMap.Count > 0)
            {
                battle = SBattleLogicModule.Instance.battleMap.First((pair) => true).Value;
            }

            if (battle == null)
            {
                GUILayout.Label("未找到战斗实例");
                return;
            }

            if (battle.isEnd || battle.playCtrl == null)
            {
                GUILayout.Label("战斗已结算");
                return;
            }

            this._Scroll = EditorGUILayout.BeginScrollView(this._Scroll);
            EditorGUILayout.BeginHorizontal();

#region 角色列表

            EditorGUILayout.BeginVertical(GUILayout.Width(330));
            EditorGUILayout.BeginVertical();

            int nRoundNum = battle.playCtrl.realRound;
            if (BattleEditorTools.IntField("回合数", ref nRoundNum))
            {
                battle.playCtrl.realRound = nRoundNum;
            }

            this._UnitsScroll = EditorGUILayout.BeginScrollView(this._UnitsScroll);
            var rTeams = battle.playCtrl.teamCtrl.teams;
            var rTurnDict = battle.playCtrl.queueCtrl.QueueDict;
            foreach (var rPair in rTeams)
            {
                EditorGUILayout.LabelField("----------------------");

                var rTeam = rPair.Value;
                var rUnits = rTeam.units;
                for (int j = 0; j < rUnits.Count; j++)
                {
                    var rUnit = rUnits[j];
                    var b = this._selectUnits.Contains(rUnit);
                    string btn = "";
                    if (rTurnDict.TryGetValue(rUnit, out var rTurn))
                    {
                        btn = $"UID:{rUnit.GUID}({rTurn?.executeCount}/({rTurn?.maxExecuteCount}+{rTurn.extraExecuteCount})_{rTurn.executeRound})";
                    }
                    else
                    {
                        btn = $"UID:{rUnit.GUID}";
                    }
                    EditorGUILayout.BeginHorizontal();
                    if (BattleEditorTools.ShowSelectBtn(btn, ref b, 230))
                    {
                        if (!this._selectUnits.Contains(rUnit))
                        {
                            this._selectUnits.Add(rUnit);
                            this._selectUnits.Sort((x, y) => x.GUID.CompareTo(y.GUID));
                        }
                    }
                    else
                    {
                        this._selectUnits.Remove(rUnit);
                    }
                    if (GUILayout.Button("GameObject"))
                    {
                        var rViewComp = BattleManager.Instance.ctrl.data.GetUnit(rUnit.GUID).GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
                        if (rViewComp != null)
                        {
                            Selection.activeObject = rViewComp.transform;
                        }
                    }
                    EditorGUILayout.EndHorizontal();
                }
            }
            this._selectUnits.RemoveAll((x) => !battle.playCtrl.unitCtrl.units.Contains(x));
            EditorGUILayout.EndScrollView();
            EditorGUILayout.EndVertical();

            EditorGUILayout.BeginVertical();
            EditorGUILayout.LabelField($"Round:{battle.playCtrl.realRound}");
            BattleEditorTools.ShowSelectBtn("属性", ref this._ShowProperty);
            BattleEditorTools.ShowSelectBtn("本地属性", ref this._showLocalProperty);
            BattleEditorTools.ShowSelectBtn("属性详情", ref this._ShowPropertyDetail);
            BattleEditorTools.ShowSelectBtn("技能", ref this._ShowSkill);
            BattleEditorTools.ShowSelectBtn("Buff", ref this._ShowBuff);
            BattleEditorTools.ShowSelectBtn("CustomProperty", ref this._ShowCustomProperty);
            if (this._selectUnits != null && this._selectUnits.Count > 0)
            {
                // if (BattleEditorTools.Button("GameObject"))
                // {
                //     var rViewComp = this._selectUnits.First().GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent);
                //     if (rViewComp != null)
                //     {
                //         Selection.activeObject = rViewComp.transform;
                //     }
                // }
            }

            EditorGUILayout.EndVertical();
            EditorGUILayout.EndVertical();

#endregion

#region 属性

            if (this._ShowProperty)
            {
                foreach (var unit in this._selectUnits)
                {
                    EditorGUILayout.BeginVertical(GUILayout.Width(430));
                    if (this._showLocalProperty)
                    {
                        var rUnitView = BattleManager.Instance.ctrl.data.GetUnit(unit.GUID);
                        this.DrawProperty(rUnitView);
                    }
                    else
                    {
                        this.DrawProperty(unit);
                    }
                    EditorGUILayout.EndVertical();
                }
            }

#endregion

#region 技能

            if (this._ShowSkill)
            {
                foreach (var unit in this._selectUnits)
                {
                    this.DrawSkill(unit);
                }
            }

#endregion

#region Buff

            if (this._ShowBuff)
            {
                foreach (var unit in this._selectUnits)
                {
                    this.DrawBuff(unit);
                }
            }

#endregion

#region CustomProperty

            if (this._ShowCustomProperty)
            {
                foreach (var unit in this._selectUnits)
                {
                    this.DrawCustomProperty(unit);
                }
            }

#endregion

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndScrollView();
        }

        private Dictionary<AttributeProperty, Vector2> _PropertyScroll = new Dictionary<AttributeProperty, Vector2>();
        private Dictionary<Unit, Vector2> _SkillScroll = new Dictionary<Unit, Vector2>();
        private Dictionary<Unit, Vector2> _BuffScroll = new Dictionary<Unit, Vector2>();

        private void DrawProperty(Unit unit)
        {
            GUILayout.Label($"服务器属性:{unit.GUID}");
            GUILayout.Label($"ID:{unit.configID}");
            EditorGUILayout.Space(20);
            EditorGUILayout.LabelField("位置", unit.pos.ToString());

            var rAIComp = unit.GetComponent<AIComponent>(ETComponentType.AIComponet);
            if (rAIComp != null)
            {
                rAIComp.active = EditorGUILayout.Toggle("AI", rAIComp.active);
            }
            var rShield = unit.GetComponent<BuffComponent>(ETComponentType.BuffComponent)?.shield;
            if (rShield != null)
            {
                int nValue = rShield.curShield;
                if (BattleEditorTools.IntField("护盾", ref nValue))
                {
                    var nV = nValue - rShield.curShield;
                    if (nV > 0)
                    {
                        rShield.AddShield(nV, 10);
                    }
                }
            }
            {
                var nValue = unit.weaknessPoint;
                if (BattleEditorTools.IntField("弱点", ref nValue))
                {
                    unit.weaknessPoint = nValue;
                }
            }
            var rAttr = unit.GetComponent<AttributeComponent>(ETComponentType.AttributeComponent).attr;
            var rChangeType = this.DrawProperty(rAttr);
            // 服务器修改才会同步
            if (!this._showLocalProperty && rChangeType != EAttributeType.Min)
            {
                var rResultCtrl = unit.battle.playCtrl.resultCtrl;
                var rValue = rAttr.GetAll(rChangeType);
                rResultCtrl.Add(BattleUpdateFactory.CreateAttrChange(rChangeType, EAttributeAddType.Percent, rValue.Item2, false, unit.GUID));
                rResultCtrl.Add(BattleUpdateFactory.CreateAttrChange(rChangeType, EAttributeAddType.Add, rValue.Item3, false, unit.GUID));
            }
        }

        private void DrawProperty(UnitView unit)
        {
            GUI.color = Color.red;
            GUILayout.Label($"本地属性:{unit.GUID}");
            GUI.color = Color.white;
            GUILayout.Label($"ID:{unit.configID}");
            EditorGUILayout.Space(20);
            EditorGUILayout.LabelField("位置", unit.pos.ToString());

            var nShield = unit.GetComponent<BuffViewComponent>(ETComponentType.BuffViewComponent)?.shield ?? 0;
            GUILayout.Label($"护盾:{nShield}");
            GUILayout.Label($"弱点:{unit.weaknessPoint}");
            var rAttr = unit.GetComponent<AttributeViewComponent>(ETComponentType.AttributeViewComponent).attr;
            this.DrawProperty(rAttr);
        }

        private EAttributeType DrawProperty(AttributeProperty attr)
        {
            if (!this._PropertyScroll.TryGetValue(attr, out _))
            {
                this._PropertyScroll.Add(attr, Vector2.zero);
            }
            var changeType = EAttributeType.Min;
            this._PropertyScroll[attr] = EditorGUILayout.BeginScrollView(this._PropertyScroll[attr]);

            for (int i = (int)EAttributeType.Min + 1; i < (int)EAttributeType.Max; i++)
            {
                var rType = (EAttributeType)i;
                var nValue = attr.Get(rType).ToInt();
                EditorGUILayout.LabelField(rType.ToString(), nValue.ToString());
                var rRealValue = attr.GetAll(rType);
                if (this._ShowPropertyDetail &&
                    (BattleEditorTools.IntField("    面板：", ref rRealValue.Item1) ||
                     BattleEditorTools.IntField("    万分比：", ref rRealValue.Item2) ||
                     BattleEditorTools.IntField("    加：", ref rRealValue.Item3)))
                {
                    attr.Set(rType, rRealValue.Item1);
                    attr.Set(rType, rRealValue.Item2, EAttributeAddType.Percent);
                    attr.Set(rType, rRealValue.Item3, EAttributeAddType.Add);
                    changeType = rType;
                }
            }
            GUILayout.EndScrollView();
            return changeType;
        }

        private void DrawSkill(Unit unit)
        {
            EditorGUILayout.BeginVertical(GUILayout.Width(330));
            EditorGUILayout.LabelField($"技能:{unit.GUID}");
            EditorGUILayout.Space(20);
            var rComp = unit.GetComponent<SkillComponent>(ETComponentType.SkillComponent);
            if (rComp != null)
            {
                BattleEditorTools.IntField("SkillID", ref this._TempSkill);
                BattleEditorTools.IntField("SkillLv", ref this._TempSkillLv);
                if (BattleEditorTools.Button("Add", 300))
                {
                    var rConfig = SkillFactory.GetConfig(this._TempSkill);
                    if (rConfig != null)
                    {
                        var rSkill = SkillFactory.CreateSkill(this._TempSkill, rConfig, this._TempSkillLv, unit);
                        rComp.AddSkill(rSkill);
                    }
                }

                EditorGUILayout.Space(10);
                var rList = new List<Skill>(rComp.skills);
                // DrawSkill
                if (!this._SkillScroll.TryGetValue(unit, out _))
                {
                    this._SkillScroll.Add(unit, Vector2.zero);
                }

                this._SkillScroll[unit] = EditorGUILayout.BeginScrollView(this._SkillScroll[unit]);
                for (int i = 0; i < rList.Count; i++)
                {
                    if (GUILayout.Button(rList[i].ToString(), GUILayout.Width(300), GUILayout.Height(150)))
                    {
                        rComp.RemoveSkill(rList[i]);
                    }

                    EditorGUILayout.Space(5);
                }

                EditorGUILayout.EndScrollView();
            }

            EditorGUILayout.EndVertical();
        }

        private void DrawBuff(Unit unit)
        {
            EditorGUILayout.BeginVertical(GUILayout.Width(330));
            EditorGUILayout.LabelField($"Buff:{unit.GUID}");

            var rComp = unit.GetComponent<BuffComponent>(ETComponentType.BuffComponent);
            if (rComp != null)
            {
                this._TempBuffID.TryAdd(unit.GUID, 0);
                var nBuffID = this._TempBuffID[unit.GUID];
                if (BattleEditorTools.IntField("BuffID", ref nBuffID))
                {
                    this._TempBuffID[unit.GUID] = nBuffID;
                }

                if (BattleEditorTools.Button("Add", 300))
                {
                    rComp.Add(rComp, this._TempBuffID[unit.GUID]);
                }

                if (BattleEditorTools.Button("RefreshTurn", 300))
                {
                    rComp.OnRefresh();
                }

                EditorGUILayout.Space(10);
                var rList = new List<BuffHandler>(rComp.buffList);
                // DrawBuff
                if (!this._BuffScroll.TryGetValue(unit, out _))
                {
                    this._BuffScroll.Add(unit, Vector2.zero);
                }

                this._BuffScroll[unit] = EditorGUILayout.BeginScrollView(this._BuffScroll[unit]);
                for (int i = 0; i < rList.Count; i++)
                {
                    if (GUILayout.Button(rList[i].ToString(), GUILayout.Width(300), GUILayout.Height(150)))
                    {
                        rComp.Destroy(rList[i]);
                    }

                    EditorGUILayout.Space(5);
                }

                EditorGUILayout.EndScrollView();
            }

            EditorGUILayout.EndHorizontal();
        }

        private void DrawCustomProperty(Unit unit)
        {
            EditorGUILayout.BeginVertical(GUILayout.Width(330));
            EditorGUILayout.LabelField($"CustomProperty: {unit.GUID}");
            EditorGUILayout.Space(20);

            var rComp = unit.GetComponent<CustomPropertyComponent>(ETComponentType.CustomPropertyComponent);
            if (rComp != null)
            {
                var rValues = Enum.GetValues(typeof(ECustomProperty));
                foreach (var rType in rValues)
                {
                    var nKey = (int)rType;
                    if (rComp.propertyHash.TryGetValue(nKey, out var rAny))
                    {
                        EditorGUILayout.LabelField(rType.ToString(), rAny.ToString());
                    }
                }
            }
            EditorGUILayout.Space(20);
            foreach (var rPair in rComp.customHash)
            {
                EditorGUILayout.LabelField(rPair.Key, rPair.Value.ToString());
            }
            EditorGUILayout.EndVertical();
        }
    }
}